#include "creusator.h"
#include <QDebug>
#include <QPaintEngine>
#include <QLine>
#include <QFile>
#include <QResource>
#include <QtOpenGL>

Creusator::Creusator(QWidget *parent) : QGLWidget (parent)
{
    this->setParent(parent);
    this->setFocusPolicy(Qt::StrongFocus);

    init();
    m_game = new Game();


    QFile file("level5");
    file.open(QIODevice::WriteOnly);
    QDataStream out(&file);
    out << testLevel();
    file.close();

    qsrand(QTime::currentTime().msec());
    //m_globalTimerId = startTimer(50);
}


int Creusator::getNormalWidth()
{
    if(m_game->getCurrentMap())
        return m_game->getCurrentMap()->getWidth();
    return -1;
}
int Creusator::getNormalHeight()
{
    if(m_game->getCurrentMap())
        return m_game->getCurrentMap()->getHeight();
    return -1;
}

QStringList Creusator::getSavedGamesList()
{
    return m_game->getSavedGamesToString();
}


QStringList Creusator::getLevelsList()
{
    QStringList list;

    for(int i = 1; i <= m_nLevels; i++)
        list << "level" + QString::number(i);

    return list;
}

void Creusator::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter painter(this);

    fixPainterRatio(&painter);
    //painter.setRenderHint(QPainter::Antialiasing);

    m_game->draw(&painter);

    if (m_win)
    {
        QFont font;
        font.setPointSize(50);
        painter.setPen(Qt::red);
        painter.setFont(font);
        painter.drawText(x() +width()/2 -(50 *7)/2, y()+ height()/2 -50/2, "YOU WIN");
    }

    if (m_loose)
    {
        QFont font;
        font.setPointSize(50);
        painter.setPen(Qt::red);
        painter.setFont(font);
        painter.drawText(x() +width()/2 -(50 *7)/2, y()+ height()/2 -50/2, "YOU LOSE");
    }

    painter.end();
}


void Creusator::resizeEvent(QResizeEvent *event)
{
    Q_UNUSED(event);

}



void Creusator::keyPressEvent(QKeyEvent *event)
{
    if(event->isAutoRepeat()) return;

    switch(event->key())
    {
        case Qt::Key_Left :
            m_leftPressed = true;
            break;
        case Qt::Key_Up :
            m_upPressed = true;
            break;
        case Qt::Key_Right :
            m_rightPressed = true;
            break;
        case Qt::Key_Down :
            m_downPressed = true;
            break;
        case Qt::Key_Q :
            exit(0);
        case Qt::Key_P :
            switchPauseGame();
            break;
        default : return;
    }

    //if(keyPressed() == 1)  m_moveTimerId = startTimer(50);
    if(m_pause && keyPressed() > 0) startGame();
}


void Creusator::keyReleaseEvent(QKeyEvent *event)
{
    if(event->isAutoRepeat()) return;

    switch(event->key())
    {
        case Qt::Key_Left :
            m_leftPressed = false;
            break;
        case Qt::Key_Up :
            m_upPressed = false;
            break;
        case Qt::Key_Right :
            m_rightPressed = false;
            break;
        case Qt::Key_Down :
            m_downPressed = false;
            break;
        default : return;
    }

    //if(keyPressed() == 0) killTimer(m_moveTimerId);
}

void Creusator::timerEvent(QTimerEvent *event)
{
    Q_UNUSED(event);
    bool winLevel, winGame;
    QTime tempsTotal;
    tempsTotal.start();

    if(m_win || m_loose) return;

    //qDebug() << m_game->getCurrentLevel()->getPlayer();

    if(m_leftPressed)
    {
        m_game->movePlayerLeft();
        m_game->collisionsWithPlayer();
    }

    if(m_upPressed)
    {
        m_game->movePlayerUp();
        m_game->collisionsWithPlayer();
    }

    if(m_rightPressed)
    {
        m_game->movePlayerRight();
        m_game->collisionsWithPlayer();
    }

    if(m_downPressed)
    {
        m_game->movePlayerDown();
        m_game->collisionsWithPlayer();
    }

    m_game->advance(winLevel, winGame, m_loose);

    if (winLevel) pauseGame();
    if (winLevel && winGame) m_win = true;

    repaint();

    if (tempsTotal.elapsed() > m_globalTimerInterval ||
       (tempsTotal.elapsed() <  m_globalTimerInterval  &&  m_globalTimerInterval > TIMER_INTERVAL))
    {
        m_globalTimerInterval = ((tempsTotal.elapsed() > TIMER_INTERVAL) ? tempsTotal.elapsed() : TIMER_INTERVAL);
        killTimer(m_globalTimerId);
        m_globalTimerId = startTimer(m_globalTimerInterval);
    }
}



void Creusator::init()
{
    m_nLevels = 5;

    m_leftPressed = false;
    m_upPressed = false;
    m_rightPressed = false;
    m_downPressed = false;

    m_pause = true;
    m_win = false;
}


void Creusator::fixPainterRatio(QPainter *painter)
{
    Map *map = m_game->getCurrentMap();
    painter->setWindow(0, 0, map->getWidth(), map->getHeight());

    int mapWidth = m_game->getCurrentMap()->getWidth();
    int mapHeight = m_game->getCurrentMap()->getHeight();

    int newWidth = (mapWidth * height()) / mapHeight;
    int newHeight = (mapHeight * width()) / mapWidth;

    if(mapHeight * width() < mapWidth * height())
        painter->setViewport(0, (height() - newHeight) / 2, width(), newHeight);
    else
        painter->setViewport((width() - newWidth) / 2, 0, newWidth, height());
}


int Creusator::keyPressed()
{
   return (m_leftPressed + m_upPressed +
           m_rightPressed + m_downPressed);
}


void Creusator::testMap(Map *map)
{
    map->setMapItem(0, 0, new MapItem(new Door()));

    /*
    MapItem *m = new MapItem(new Block());

    map->setMapItem(0, 1, new MapItem(new Block()));
    map->setMapItem(0, 2, new MapItem(new Block()));
    map->setMapItem(0, 3, new MapItem(new Block()));
    map->setMapItem(0, 5, new MapItem(new Block()));

    for(int i = 3; i < 10; i++)
    {
        map->setMapItem(i, 4, new MapItem(new Block()));
        map->setMapItem(i, 2, new MapItem(new Block()));
    }

    for(int i = 6; i < 10; i++)
        map->setMapItem(7, i, new MapItem(new Fruit()));
    */
    int k = 0;
    for(int i = 0; i < map->getRows(); i++)
    {
        for(int j = 1; j < map->getColumns(); j++) {
            if (k %2 == 0) map->setMapItem(i, j, new MapItem(new Block()));
            else           map->setMapItem(i, j, new MapItem(new Fruit()));
            k ++;
        }
    }

}

Level * Creusator::testLevel()
{
    // Joueur
    QRect r(0, 0, 30, 40);
    Player *player = new Player(r);
    // Map
    Map *map = new Map(3, 2, 800, 600);
    testMap(map);
    // Level
    Level *level = new Level(map, player);
    // Monstres
    for (int i = 0 ; i < 2 ; i ++) {
        QRect rm(0, ((i%4)+2)*70, 20, 20);
        level->addMonster(new Monster(rm, 1));
    }
    for (int i = 0 ; i < 1 ; i ++) {
        QRect rm(0, ((i%4)+2)*70, 20, 15);
        level->addMonster(new Monster(rm, 2));
    }
    // Pierres
    for (int i = 0 ; i < 1 /*(900/57)*/ ; i ++) {
        QRect rm(57, 0, 54, 40);
        level->addRock(new Rock(rm));
    }

    return level;
}


void Creusator::startGame()
{
    m_globalTimerInterval = TIMER_INTERVAL;
    m_globalTimerId = startTimer(m_globalTimerInterval);
    m_pause = false;
}

void Creusator::pauseGame()
{
    if(m_pause) return;
    killTimer(m_globalTimerId);
    m_pause = true;
}

void Creusator::endGame()
{
    m_win = false;
    m_loose = false;
    m_game->endGame();
}

void Creusator::switchPauseGame()
{
    if(m_pause) startGame();
    else pauseGame();
}

void Creusator::saveGame(QString name, int pos)
{
    m_game->saveGame(name, pos);
}

void Creusator::loadGame(int pos)
{
    m_game->loadGame(pos);
    m_loose = false;
    m_win = false;
    pauseGame();
}

void Creusator::newGame(QStringList levels)
{
    m_game->newGame(levels);
    m_loose = false;
    m_win = false;
    pauseGame();
}

void Creusator::removeSavedGame(int pos)
{
    m_game->removeSavedGame(pos);
}
